#pragma once
#include "collection/HashMap.hpp"
#include "crypto/keys/FAQKeyPairGenerator.h"
#include "crypto/algorithms/ialgorithm/FAQCipherAlgorithm.h"
#include "crypto/algorithms/ialgorithm/FAQDigestAlgorithm.h"
#include "crypto/algorithms/ialgorithm/FAQSignAlgorithm.h"
#include "crypto/algorithms/ialgorithm/FAQMacAlgorithm.h"
#include "crypto/algorithms/ialgorithm/FAQKeyAgreementAlgorithm.h"
#include "crypto/algorithms/ialgorithm/FAQKeyDerivationFunction.h"
#include "crypto/exception/FAQCipherException.h"

namespace yzrilyzr_crypto{
	EBCLASS(FAQCryptoRegister){
	private:
	static yzrilyzr_collection::HashMap<yzrilyzr_lang::String, std::shared_ptr<FAQCipherAlgorithm>> ciphers;
	static yzrilyzr_collection::HashMap<yzrilyzr_lang::String, std::shared_ptr<FAQDigestAlgorithm>> digests;
	static yzrilyzr_collection::HashMap<yzrilyzr_lang::String, std::shared_ptr<FAQSignAlgorithm>> signers;
	static yzrilyzr_collection::HashMap<yzrilyzr_lang::String, std::shared_ptr<FAQMacAlgorithm>> macs;
	static yzrilyzr_collection::HashMap<yzrilyzr_lang::String, std::shared_ptr<FAQKeyAgreementAlgorithm>> keyAgreements;
	static yzrilyzr_collection::HashMap<yzrilyzr_lang::String, std::shared_ptr<FAQKeyDerivationFunction>> kdfs;
	static yzrilyzr_collection::HashMap<yzrilyzr_lang::String, std::shared_ptr<FAQKeyPairGenerator>> keyPairGenerators;
	void registerDefaultCiphers();
	
	// --- 辅助方法 ---
	static yzrilyzr_lang::String normalizeName(const yzrilyzr_lang::String & name){
		if(name == nullptr) return nullptr;
		// 将名称标准化为大写，以实现不区分大小写的查找
		// 对于 "AES/CBC/PKCS5Padding" 这样的组合，也统一大写
		return name.toUpperCase();
	}
	public:
	FAQCryptoRegister(){
		registerDefaultCiphers();
	}
	// --- 注册方法 ---
	static void registerKeyPairGenerator(const yzrilyzr_lang::String & name, std::shared_ptr < FAQKeyPairGenerator> kpg){
		keyPairGenerators.put(normalizeName(name), kpg);
	}
	static void registerCipher(const yzrilyzr_lang::String & name, std::shared_ptr < FAQCipherAlgorithm>cipher){
		ciphers.put(normalizeName(name), cipher);
	}
	static void registerDigest(const yzrilyzr_lang::String & name, std::shared_ptr < FAQDigestAlgorithm > digest){
		digests.put(normalizeName(name), digest);
	}
	static void registerSigner(const yzrilyzr_lang::String & name, std::shared_ptr < FAQSignAlgorithm > signer){
		signers.put(normalizeName(name), signer);
	}
	static void registerMac(const yzrilyzr_lang::String & name, std::shared_ptr < FAQMacAlgorithm > mac){
		macs.put(normalizeName(name), mac);
	}
	static void registerKeyAgreement(const yzrilyzr_lang::String & name, std::shared_ptr < FAQKeyAgreementAlgorithm > ka){
		keyAgreements.put(normalizeName(name), ka);
	}
	static void registerKdf(const yzrilyzr_lang::String & name, std::shared_ptr < FAQKeyDerivationFunction >kdf){
		kdfs.put(normalizeName(name), kdf);
	}
	// --- 获取方法 ---
	static std::shared_ptr<FAQKeyPairGenerator> getKeyPairGenerator(const yzrilyzr_lang::String & name){
		auto kpg=keyPairGenerators.get(normalizeName(name));
		if(!kpg.has_value()) throw FAQNoSuchAlgorithmException("KeyPairGenerator " + name + " not found");
		return std::dynamic_pointer_cast<FAQKeyPairGenerator>(kpg.value()->newInstance());
	}
	static std::shared_ptr<FAQCipherAlgorithm> getCipher(const yzrilyzr_lang::String & name){
		auto cipher=ciphers.get(normalizeName(name));
		if(!cipher.has_value()) throw FAQNoSuchAlgorithmException("Cipher " + name + " not found");
		return std::dynamic_pointer_cast<FAQCipherAlgorithm>(cipher.value()->newInstance());
	}
	static std::shared_ptr<FAQDigestAlgorithm> getDigest(const yzrilyzr_lang::String & name){
		auto digest=digests.get(normalizeName(name));
		if(!digest.has_value()) throw FAQNoSuchAlgorithmException("Digest " + name + " not found");
		return std::dynamic_pointer_cast<FAQDigestAlgorithm>(digest.value()->newInstance());
	}
	static std::shared_ptr<FAQSignAlgorithm> getSigner(const yzrilyzr_lang::String & name){
		auto signer=signers.get(normalizeName(name));
		if(!signer.has_value()) throw FAQNoSuchAlgorithmException("Signer " + name + " not found");
		return std::dynamic_pointer_cast<FAQSignAlgorithm>(signer.value()->newInstance());
	}
	static std::shared_ptr<FAQMacAlgorithm> getMac(const yzrilyzr_lang::String & name){
		auto mac=macs.get(normalizeName(name));
		if(!mac.has_value()) throw new FAQNoSuchAlgorithmException("MAC " + name + " not found");
		return std::dynamic_pointer_cast<FAQMacAlgorithm>(mac.value()->newInstance());
	}
	static std::shared_ptr<FAQKeyAgreementAlgorithm> getKeyAgreement(const yzrilyzr_lang::String & name){
		auto ka=keyAgreements.get(normalizeName(name));
		if(!ka.has_value()) throw new FAQNoSuchAlgorithmException("KeyAgreement " + name + " not found");
		return std::dynamic_pointer_cast<FAQKeyAgreementAlgorithm>(ka.value()->newInstance());
	}
	static std::shared_ptr<FAQKeyDerivationFunction> getKdf(const yzrilyzr_lang::String & name){
		auto kdf=kdfs.get(normalizeName(name));
		if(!kdf.has_value()) throw new FAQNoSuchAlgorithmException("KDF " + name + " not found");
		return std::dynamic_pointer_cast<FAQKeyDerivationFunction>(kdf.value()->newInstance());
	}
	};
	//static FAQCryptoRegister _FAQCryptoRegister;
}